/*
 */
package org.vectrics.project.task;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.vectrics.SystemException;
import org.vectrics.common.db.Auditable;
import org.vectrics.common.db.ExpirableUtils;
import org.vectrics.common.db.RecordObject;
import org.vectrics.common.db.Voidable;
import org.vectrics.common.util.DateSync;
import org.vectrics.common.util.DateUtil;
import org.vectrics.company.Company;
import org.vectrics.provider.CoreServiceLocator;
import org.vectrics.user.Person;

/**
 * @author mmoore
 */
public class Task implements Voidable, Auditable {
	public static final String TYPE_TASK = "task";
	public static final String TYPE_PROJECT = "project";
	public static final String TYPE_BENCHMARK = "bench";

	private Long id = null;
    private String typeCode = Task.TYPE_TASK;
    private Task parent = null;
    private Collection relationships = new ArrayList();
    private Date dueDate = null;
    private Date schedStartTime = null;
    private Date schedEndTime = null;
    private Date actualStartTime = null;
    private Date actualEndTime = null;
    private long estimatedSecondsRequired = DateUtil.MILLIS_IN_A_DAY;
    private long percentComplete = 0;
    private String description = null;
    private String referenceCode = null;
    private TaskCategory taskCategory = null;
    private boolean voided = false;
    private Company company = null;
    private Set taskResources = new HashSet();
    private Set taskStatusList = new HashSet();
    private Set taskPrerequisites = new HashSet();
    private List attachments = new ArrayList();
    private boolean userTask = false;
	private Person createdBy = null;
	private Date createdDate = null;
	private Person lastModifiedBy = null;
	private Date lastModifiedDate = null;
    
    /**
     * @return Returns the id.
     */
    public Long getId() {
        return id;
    }
    
    /**
     * @param id The id to set.
     */
    public void setId(Long id) {
        this.id = id;
    }

	/**
     * @return Returns the children.
     */
    public List getChildren() {
    	List children = CoreServiceLocator.getProjectService().findTaskChildren(this);
    	return(children);
    }
    
	public Task addChild() {
		Task child = new Task();
		child.setParent(this);
		child.setTaskResources(this.getTaskResources());
		child.setCompany(this.getCompany());
		child.setSchedStartTime(this.getSchedStartTime());
		child.setSchedEndTime(this.getSchedEndTime());
		child.setDueDate(this.getDueDate());
		return(child);
	}

	
	public TaskResource addResource(Person person, String description) {
		TaskResource taskResource = new TaskResource();
		taskResource.setDescription(description);
		taskResource.setPerson(person);
		taskResource.setTask(this);
		taskResource.setDateStart(this.getSchedStartTime());
		this.taskResources.add(taskResource);
		return(taskResource);
	}
	
	/**
	 * @return Returns the referenceCode.
	 */
	public String getReferenceCode() {
		return referenceCode;
	}
	
	/**
	 * @param referenceCode The referenceCode to set.
	 */
	public void setReferenceCode(String referenceCode) {
		this.referenceCode = referenceCode;
	}
	
    /**
	 * @return Returns the typeCode.
	 */
	public String getTypeCode() {
		return typeCode;
	}

	/**
	 * @param typeCode The typeCode to set.
	 */
	public void setTypeCode(String typeCode) {
		this.typeCode = typeCode;
	}

	/**
     * @return Returns the description.
     */
    public String getDescription() {
        return description;
    }
    
    /**
     * @param description The description to set.
     */
    public void setDescription(String description) {
        this.description = description;
    }
    
    /**
     * @return Returns the parent.
     */
    public Task getParent() {
        return parent;
    }
    /**
     * @param parent The parent to set.
     */
    public void setParent(Task parent) {
        this.parent = parent;
    }
    
    
    /**
	 * @return Returns the actualEndTime.
	 */
	public Date getActualEndTime() {
		return actualEndTime;
	}
	/**
	 * @param actualEndTime The actualEndTime to set.
	 */
	public void setActualEndTime(Date actualEndTime) {
		this.actualEndTime = actualEndTime;
	}
	/**
	 * @return Returns the actualStartTime.
	 */
	public Date getActualStartTime() {
		return actualStartTime;
	}
	/**
	 * @param actualStartTime The actualStartTime to set.
	 */
	public void setActualStartTime(Date actualStartTime) {
		this.actualStartTime = actualStartTime;
	}
	/**
	 * @return Returns the dueDate.
	 */
	public Date getDueDate() {
		return dueDate;
	}
	/**
	 * @param dueDate The dueDate to set.
	 */
	public void setDueDate(Date dueDate) {
		this.dueDate = dueDate;
	}
	/**
	 * @return Returns the schedEndTime.
	 */
	public Date getSchedEndTime() {
		return schedEndTime;
	}
	/**
	 * @param schedEndTime The schedEndTime to set.
	 */
	public void setSchedEndTime(Date schedEndTime) {
		this.schedEndTime = schedEndTime;
	}
	/**
	 * @return Returns the schedStartTime.
	 */
	public Date getSchedStartTime() {
		return schedStartTime;
	}
	/**
	 * @param schedStartTime The schedStartTime to set.
	 */
	public void setSchedStartTime(Date schedStartTime) {
		this.schedStartTime = schedStartTime;
	}

    /**
     * @return Returns the relationships.
     */
    public Collection getRelationships() {
        return relationships;
    }
    /**
     * @param relationships The relationships to set.
     */
    public void setRelationships(Collection relationships) {
        this.relationships = relationships;
    }
    
    
    /**
	 * @return Returns the taskCategory.
	 */
	public TaskCategory getTaskCategory() {
		return taskCategory;
	}
	/**
	 * @param taskCategory The taskCategory to set.
	 */
	public void setTaskCategory(TaskCategory taskCategory) {
		this.taskCategory = taskCategory;
	}
	/**
	 * @return Returns the company.
	 */
	public Company getCompany() {
		return company;
	}
	/**
	 * @param company The company to set.
	 */
	public void setCompany(Company company) {
		this.company = company;
	}

	/**
	 * @return Returns the taskResources.
	 */
	public Set getTaskResources() {
		return taskResources;
	}
	/**
	 * @param taskResources The taskResources to set.
	 */
	public void setTaskResources(Set taskResources) {
		this.taskResources = taskResources;
	}

	public TaskStatus getCurrentStatus() {
		TaskStatus current = (TaskStatus)ExpirableUtils.getCurrent(this.taskStatusList);
		return(current);
	}
	
	public void setStatus(String statusTypeCode, Person changedBy) {
		TaskStatusType statusType = CoreServiceLocator.getProjectService().findTaskStatusType(statusTypeCode);
		this.setStatus(statusType, changedBy);
	}
	
	public void setStatus(TaskStatusType statusType, Person changedBy) {
		Date now = DateSync.getCurrentTime();
		TaskStatus currentStatus = this.getCurrentStatus();
		if (currentStatus == null) {
			
		} else {
			if (currentStatus.getTaskStatusType().getCode().equals(statusType.getCode()))
				throw new SystemException("Attempt to assign the same status as the current status to a task.");
			currentStatus.setDateEnd(now);
		}
		TaskStatus newStatus = new TaskStatus();
		newStatus.setTask(this);
		newStatus.setDateStart(now);
		newStatus.setChangedBy(changedBy);
		newStatus.setTaskStatusType(statusType);
		this.taskStatusList.add(newStatus);
	}
	
	
	/**
	 * @return Returns the taskStatusList.
	 */
	public Set getTaskStatusList() {
		return taskStatusList;
	}

	/**
	 * @param taskStatusList The taskStatusList to set.
	 */
	public void setTaskStatusList(Set taskStatusList) {
		this.taskStatusList = taskStatusList;
	}

	
	
	/**
	 * @return Returns the attachments.
	 */
	public List getAttachments() {
		return attachments;
	}

	/**
	 * @param attachments The attachments to set.
	 */
	public void setAttachments(List attachments) {
		this.attachments = attachments;
	}

	
	
	/**
	 * @return Returns the userTask.
	 */
	public boolean getUserTask() {
		return userTask;
	}

	/**
	 * @param userTask The userTask to set.
	 */
	public void setUserTask(boolean userTask) {
		this.userTask = userTask;
	}

	
	
	/**
	 * @return Returns the createdDate.
	 */
	public Date getCreatedDate() {
		return createdDate;
	}

	/**
	 * @param createdDate The createdDate to set.
	 */
	public void setCreatedDate(Date createdDate) {
		this.createdDate = createdDate;
	}

	/**
	 * @return Returns the estimatedSecondsRequired.
	 */
	public long getEstimatedSecondsRequired() {
		return estimatedSecondsRequired;
	}

	/**
	 * @param estimatedSecondsRequired The estimatedSecondsRequired to set.
	 */
	public void setEstimatedSecondsRequired(long estimatedSecondsRequired) {
		this.estimatedSecondsRequired = estimatedSecondsRequired;
	}

	/**
	 * @return Returns the taskPrerequisites.
	 */
	public Set getTaskPrerequisites() {
		return taskPrerequisites;
	}

	/**
	 * @param taskPrerequisites The taskPrerequisites to set.
	 */
	public void setTaskPrerequisites(Set taskPrerequisites) {
		this.taskPrerequisites = taskPrerequisites;
	}

	/**
	 * @return Returns the percentComplete.
	 */
	public long getPercentComplete() {
		return percentComplete;
	}

	/**
	 * @param percentComplete The percentComplete to set.
	 */
	public void setPercentComplete(long percentComplete) {
		this.percentComplete = percentComplete;
	}

	/**
     * @return Returns the voided.
     */
    public boolean getVoided() {
        return voided;
    }

    /**
     * @param voided The voided to set.
     */
    public void setVoided(boolean voided) {
        this.voided = voided;
    }

	/**
	 * @return Returns the createdBy.
	 */
	public Person getCreatedBy() {
		return createdBy;
	}

	/**
	 * @param createdBy The createdBy to set.
	 */
	public void setCreatedBy(Person createdBy) {
		this.createdBy = createdBy;
	}

	/**
	 * @return Returns the lastModifiedBy.
	 */
	public Person getLastModifiedBy() {
		return lastModifiedBy;
	}

	/**
	 * @param lastModifiedBy The lastModifiedBy to set.
	 */
	public void setLastModifiedBy(Person lastModifiedBy) {
		this.lastModifiedBy = lastModifiedBy;
	}

	/**
	 * @return Returns the lastModifiedDate.
	 */
	public Date getLastModifiedDate() {
		return lastModifiedDate;
	}

	/**
	 * @param lastModifiedDate The lastModifiedDate to set.
	 */
	public void setLastModifiedDate(Date lastModifiedDate) {
		this.lastModifiedDate = lastModifiedDate;
	}


	public boolean logEntityChanges() {
		return(true);
	}
    
    
}
